
// ShipCustomiser
// J.H. Moritz Kraft, 12 May 2008
// written for Sixth Fleet DaDB


// Namespace
if ( typeof ( SF ) == "undefined" ) var SF = {};


/////////////////////////////
/// /////////////////////////
/// Main class definition ///
/// /////////////////////////
/////////////////////////////

SF.ShipCustomiser = {

  width: 600,
  currentHullId: 0,
  listeners: [],
  currentStructure: 0,
  currentPower: 0,
  currentCrew: 0,
  currentData: {
    facilitates: {
    },
    requires: {
    }
  },

  initialise: function( setupArgs )
  {
    if ( typeof ( setupArgs ) != "undefined" )
    {
      if ( typeof ( setupArgs.width )  != "undefined" ) this.width  = setupArgs.width;
    }
    this.createControlMarkup();
    this.components = [];
    for ( var key in SF.Components )
    {
      var p = new SF.UIPanel( key, SF.Components[key], this );
      this.components.push( p );
      $( "#div_components" ).append( p.domNode );
    }
    this.currentHullId = 1;
    this.fireEvent( new SF.ConstraintObject( this.getHullData( this.currentHullId ), 1, true ) );
  },

  createControlMarkup: function()
  {
    $( "#div_shipcustomiser" ).css( "width", this.width );
    var divCtrl = $( '<div id="div_control" />' );
    divCtrl.appendTo( "#div_shipcustomiser" );
    divCtrl.append( 'Select a hull class:' );
    // <select/> tag for the ship's hull
    var hullSelector = $( '<select id="select_hulls" />' );
    hullSelector.change( function()
    {
      SF.ShipCustomiser.fireEvent( new SF.ConstraintObject( SF.ShipCustomiser.getHullData( SF.ShipCustomiser.currentHullId ), 1, false ) );
      SF.ShipCustomiser.currentHullId = parseInt( this.value );
      SF.ShipCustomiser.fireEvent( new SF.ConstraintObject( SF.ShipCustomiser.getHullData( SF.ShipCustomiser.currentHullId ), 1, true ) );
    });
    for( var key in SF.Hulls.rows )
    {
      hullSelector.append( '<option value="' + SF.Hulls.rows[key].id + '">' + SF.Hulls.rows[key].title + '</option>' );
    }
    divCtrl.append( hullSelector );
    // other controls and status labels
    divCtrl.append( ' <button id="button_print">print current specifications</button>' );
    var divStatus = $( '<div style="text-align: center; padding: 5px;" />' );
    divStatus.appendTo( divCtrl );
    divStatus.append( ' SP: <span id="span_structure">0</span>,' );
    divStatus.append( ' Power: <span id="span_power">0</span>,' );
    divStatus.append( ' Crew: <span id="span_crew">0</span>' );
    $( "#div_shipcustomiser" ).append( '<div id="div_components" />' );
  },

  updateStatus: function( key, value )
  {
    var current = 0;
    if ( $( "#span_" + key ).html() != "" ) current = parseInt( $( "#span_" + key ).html() );
    current = current + value;
    if ( current < 0 )
    {
      $("#button_print").attr( "disabled", true );
      $("#span_" + key).css( "color", "red" );
    }
    else
    {
      $("#button_print").attr( "disabled", false );
      $("#span_" + key).css( "color", "green" );
    }
    if ( current == 0 ) current = "0";
    $( "#span_" + key ).html( current );
    switch( key )
    {
      case "structure": this.currentStructure = current; break;
      case "power":     this.currentPower = current;     break;
      case "crew":      this.currentCrew = current;      break;
    }
  },

  getHullData: function( id )
  {
    for( var key in SF.Hulls.rows )
    {
      if ( SF.Hulls.rows[key].id == id ) return SF.Hulls.rows[key];
    }
    return false;
  },

  getUIPanelRow: function( name, id )
  {
    for( var key in this.components )
    {
      if ( this.components[key].name == name )
      {
        for ( var k in this.components[key].rows )
        {
          if ( this.components[key].rows[k].data.id == id ) return this.components[key].rows[k];
        }
      }
    }
    return false;
  },

  addListener: function( listenerObject )
  {
    this.listeners.push( listenerObject );
  },

  fireEvent: function( eventObject )
  {
    var mul = 1;
    if ( eventObject.invert ) mul = -1;
    this.updateStatus( "structure", eventObject.structure );
    this.updateStatus( "power", eventObject.power );
    this.updateStatus( "crew", eventObject.crew );
    for ( var it in this.listeners ) this.listeners[it].eventFired( eventObject );
  },

};


///////////////////////////////
/// ///////////////////////////
/// Other class definitions ///
/// ///////////////////////////
///////////////////////////////


/// Class UIPanelRow

SF.UIPanelRow = function( name, dataset )
{
  this.data = dataset;
  this.display = "none";
  this.checked = false;
  this.value = 0;
  this.constraints = new SF.ConstraintObject( this.data, 1, true );
  // Markup
  this.domNode = $( '<tr class="componentpanelrow" id="tr_' + name + '_' + this.data.id + '" style="display: ' + this.display + ';" />' );
  this.checkbox = $( '<input type="checkbox" id="checkbox_' + name + '_' + this.data.id + '" />' );
  this.input = $( '<input type="text" id="input_' + name + '_' + this.data.id + '" class="input_number" disabled="true" />' );
  this.domNode.append( $( '<td />' ).append( this.checkbox ) );
  this.domNode.append( $( '<td width="120" />' ).append( this.data.title ) );
  this.domNode.append( $( '<td />' ).append( this.input ) );
  // Event handler
  this.checkbox.change( function()
  {
    // this <> that...
    var idInfo = SF.getElementIdInfo( $(this).attr( "id" ) );
    var that = SF.ShipCustomiser.getUIPanelRow( idInfo.type, idInfo.id );

    var count = parseInt( $( "#input_" + idInfo.type + "_" + idInfo.id ).val() );

    if ( !that ) { alert( "meh..." ); return; }
    if ( typeof( $(this).attr( "checked" ) ) != "undefined" )
    {
      that.setChecked( true );
      if ( that.value < 1 ) that.setValue( 1 );
      that.input.removeAttr( "disabled" );
    }
    else
    {
      that.setChecked( false );
      that.input.attr( "disabled", "true" );
    }
    SF.ShipCustomiser.fireEvent( new SF.ConstraintObject( that.data, that.value, this.checked ) );
  });
  this.input.keyup( function()
  {
    // this <> that...
    var idInfo = SF.getElementIdInfo( $(this).attr( "id" ) );
    var that = SF.ShipCustomiser.getUIPanelRow( idInfo.type, idInfo.id );
    if ( !that ) { alert( "meh..." ); return; }
    var oldValue = that.value;
    var newValue = parseInt( $(this).val() );
    if ( $(this).val() == "" ) newValue = 0;
    that.setValue( newValue );
    SF.ShipCustomiser.fireEvent( new SF.ConstraintObject( that.data, -1 * ( oldValue - newValue ), true ) );
  });
  // Methods
  this.applyConstraint = function( constraint )
  {
    // decide whether or not to display this thing
    var display = true;
    var curStructure = 0;
    if( SF.ShipCustomiser.currentStructure != "" && SF.ShipCustomiser.currentStructure != "NaN" ) curStructure = parseInt( SF.ShipCustomiser.currentStructure );
    var curPower = 0;
    if( SF.ShipCustomiser.currentPower != "" && SF.ShipCustomiser.currentPower != "NaN" ) curPower = parseInt( SF.ShipCustomiser.currentPower );
    var curCrew = 0;
    if( SF.ShipCustomiser.currentCrew != "" && SF.ShipCustomiser.currentCrew != "NaN" ) curCrew = parseInt( SF.ShipCustomiser.currentCrew );
    var chkStructure = curStructure + this.constraints.structure;
    var chkPower     = curPower + this.constraints.power;
    var chkCrew      = curCrew + this.constraints.crew;
    if ( this.constraints.structure < 0 ) { if ( chkStructure < 0 ) display = false; }
    if ( this.constraints.power     < 0 ) { if ( chkPower     < 0 ) display = false; }
    if ( this.constraints.crew      < 0 ) { if ( chkCrew      < 0 ) display = false; }
    if ( display ) this.domNode.css( "display", "block" );
    else
    {
      if ( !this.checked ) this.domNode.css( "display", "none" );
    }
  };
  this.setDisplay = function( str )
  {
    this.display = str;
    $(this).css( "display", str );
  };
  this.setChecked = function( bool )
  {
    this.checked = bool;
    if ( this.checked ) $(this.checkbox).attr( "checked", "true" );
    else $(this.checkbox).removeAttr( "checked" );
  };
  this.setValue = function( num )
  {
    this.value = num;
    this.input.val( this.value );
  };
  this.eventFired = function( eventObject )
  {
    this.applyConstraint( eventObject );
  };
};


/// Class UIPanel

SF.UIPanel = function( str, components, eventDispatcher )
{
  this.rows = [];
  this.name = str;
  this.title = components.title;
  this.domNode = $( '<div id="div_' + this.name + '" class="componentpanel" />' );
  this.domNode.append( '<h3>' + this.title + '</h3>' );
  var table = $( '<table />' );
  this.domNode.append( table );
  for ( var it in components.rows )
  {
    var row = new SF.UIPanelRow( this.name, components.rows[it] );
    this.rows.push( row );
    table.append( row.domNode );
    eventDispatcher.addListener( row );
  }
};


/// Class ConstraintObject

SF.ConstraintObject = function( dataset, count, select )
{
  this.invert = !select;
  var mul = 1;
  if ( !select ) mul = -1;
  this.structure = 0;
  this.power     = 0;
  this.crew      = 0;
  if ( dataset.hasOwnProperty( "requires" ) )
  {
    for ( var k in dataset.requires )
    {
      switch ( k )
      {
        case "structure": this.structure -= count * mul * dataset.requires.structure; break;
        case "power":     this.power     -= count * mul * dataset.requires.power;     break;
        case "crew":      this.crew      -= count * mul * dataset.requires.crew;      break;
      }
    }
  }
  if ( dataset.hasOwnProperty( "facilitates" ) )
  {
    for ( var k in dataset.facilitates )
    {
      switch ( k )
      {
        case "structure": this.structure += count * mul * dataset.facilitates.structure; break;
        case "power":     this.power     += count * mul * dataset.facilitates.power;     break;
        case "crew":      this.crew      += count * mul * dataset.facilitates.crew;      break;
      }
    }
  }
};


////////////////////////////
/// ////////////////////////
/// Function definitions ///
/// ////////////////////////
////////////////////////////


/// Function getElementIdInfo
/// - parses the string value of an html id attribute
/// - returns an object with a dataset id (integer) and dataset type (string)

SF.getElementIdInfo = function( str )
{
  var obj = {};
  // dataset id:
  var delimiter_id = str.lastIndexOf( "_" );
  obj.id = parseInt( str.substr( delimiter_id + 1 ) );
  var rows = [];
  // dataset type:
  var delimiter_type = str.indexOf( "_" );
  obj.type = str.substr( delimiter_type + 1, delimiter_id - delimiter_type - 1 );
  return obj;
};

function debug( str )
{
  var previous = $( "#debug" ).html();
  if ( previous != "" ) previous += "\n";
  $( "#debug" ).html( previous + str );
  document.getElementById( "debug" ).scrollTop = document.getElementById( "debug" ).scrollHeight;
}
